package PseudoRandomNumberAlgorithm;

import NumTheory.NumTheory;

import java.math.BigInteger;
import java.util.Random;

// BBS伪随机数算法
public class BlumBlumShub {
    // 大素数 p
    private BigInteger p;
    // 大素数 q
    private BigInteger q;

    private static final NumTheory numTheory = new NumTheory();

    /**
     * 大素数生成函数
     *
     * @return 返回大素数
     */
    private BigInteger getBigPrime() {

        Random random = new Random();
        BigInteger res = null;
        int n = random.nextInt(4) + 8;
        BigInteger four = BigInteger.valueOf(4);
        BigInteger three = BigInteger.valueOf(3);
        do {
            res = new BigInteger(n, random);
            res = res.multiply(four).add(three);
            // 对伪素数进行素性检测，如果不是素数，则重新生成伪素数
        } while (!numTheory.MRtest(res, 5));

        return res;
    }

    /**
     * 伪随机数生成函数
     *
     * @param num 比特位数
     * @return 返回一个随机的大整数
     */
    private String getBBS(int num) {
        BigInteger zero = BigInteger.ZERO;

        // 大素数 p
        BigInteger p = getBigPrime();
        // 大素数 q，并且 q 和 p 不相同
        BigInteger q = getBigPrime();
        while (p.equals(q)) {
            q = getBigPrime();
        }

        Random rnd = new Random();
        BigInteger n = p.multiply(q);
        BigInteger s;
        do {
            s = new BigInteger(rnd.nextInt(4), rnd);
        } while (s.mod(p).equals(zero) || s.mod(q).equals(zero));

        return getBBS(p, q, s, num);
    }


    public String getBBS(BigInteger p, BigInteger q, BigInteger s, int num) {
        // random bit stream
        StringBuilder rbs = new StringBuilder(num);

        BigInteger n = p.multiply(q);

        BigInteger x = s.pow(2).mod(n);
        for (int i = 0; i < num; i++) {
            x = x.pow(2).mod(n);
            rbs.append((x.mod(BigInteger.valueOf(2))).intValue());
        }
        return rbs.substring(0);
    }
}
